﻿using System;
using System.Diagnostics;
using System.IO;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using HttpPublish;
using mshtml;
using SyncInfoDict = System.Collections.Generic.Dictionary<string, HttpPublish.SyncInfo>;

namespace HttpSync
{
    internal delegate void SyncInfoCallbackDelegate(string jsonResult);

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class SyncView : Form
    {
        public SyncView()
        {
            InitializeComponent();
            Form1();
        }

        //private WebBrowser syncBrowser = new WebBrowser();
        //private Button button1 = new Button();

        private void Form1()
        {
            //button1.Text = "call script code from client code";
            //button1.Dock = DockStyle.Top;
            //button1.Click += new EventHandler(Button1Click);
            //syncBrowser.Dock = DockStyle.Fill;
            //Controls.Add(syncBrowser);
            //Controls.Add(button1);
            Load += Form1Load;
        }

        private void Form1Load(object sender, EventArgs e)
        {
            syncBrowser.AllowWebBrowserDrop = false;
            syncBrowser.IsWebBrowserContextMenuEnabled = false;
            syncBrowser.WebBrowserShortcutsEnabled = false;
            syncBrowser.ObjectForScripting = this;

#if DEBUG
            syncBrowser.ScriptErrorsSuppressed = false;
#else
            syncBrowser.ScriptErrorsSuppressed = true;
#endif

            syncBrowser.DocumentText = File.ReadAllText(Publisher.ScriptPath("Views/SyncView.html"));
        }

        public void Test(String message)
        {
            MessageBox.Show(message, "client code");
        }

        public string LogText()
        {
            return Log.Logtext;
        }

        public void LogClear()
        {
            Log.Clear();
        }

        public bool AutoSync()
        {
            return Program.AutoSync;
        }

        public void GetSyncInfo()
        {
            var config = Program.Config;

            var t1 = new Thread(
                delegate()
                {
                    try
                    {

                        Log.Trace("starting to get file list");
                        var syncInfos = Publisher.GetSyncFiles(config);
                        var jsonResult = JsonHelper.Serialize(syncInfos);
                        var rx1 = new Regex(@"""\\\/Date\((-?\d+)\)\\\/""", RegexOptions.Multiline);
                        var rx2 = new Regex(@"""\\\/Date\((-?\d+)([-+]?)0+(\d*)\)\\\/""", RegexOptions.Multiline);
                        jsonResult = rx1.Replace(jsonResult, @"new Date($1)");
                        jsonResult = rx2.Replace(jsonResult, @"new Date($1 $2 ($3*36000))");
                        Invoke(new SyncInfoCallbackDelegate(SyncInfoCallback), jsonResult);
                    }
                    catch (Exception ex)
                    {
                        Log.Trace(ex.ToString());
                        Invoke(new SyncInfoCallbackDelegate(SyncErrorCallback), ex.ToString());
                    }
                });
            t1.Start();
        }

        private void SyncInfoCallback(string jsonResult)
        {
            Log.Trace("done getting file list");
            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            syncBrowser.Document.InvokeScript("ShowList", new[] { jsonResult });
        }

        private void SyncErrorCallback(string errorMsg)
        {
            Log.Trace("error getting file list: " + errorMsg);
            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            syncBrowser.Document.InvokeScript("ShowError", new[] { errorMsg });
        }

        private void SyncRestart(string msg)
        {
            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            syncBrowser.Document.InvokeScript("Start");
        }

        /*
                private void Button1Click(object sender, EventArgs e)
                {
                    Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
                    syncBrowser.Document.InvokeScript("test",
                        new[] { "called from client code" });
                }
        */

        public void SyncDates(string jsonInfo)
        {
            Log.Clear();
            var infoDict = JsonHelper.Deserialize<SyncInfoDict>(jsonInfo);
            var t1 = new Thread(delegate()
            {
                Publisher.SyncDates(Program.Config, infoDict);
                Invoke(new SyncInfoCallbackDelegate(SyncRestart), "");
            });
            t1.Start();
        }

        public void Sync()
        {
            Log.Clear();
            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            var infoDict = JsonHelper.Deserialize<SyncInfoDict>((string)syncBrowser.Document.InvokeScript("InfoList"));
            var t1 = new Thread(delegate()
            {
                Publisher.Publish(Program.Config, infoDict);
                Invoke(new SyncInfoCallbackDelegate(SyncRestart), "");
            });
            t1.Start();
        }

        private void SyncButtonClick(object sender, EventArgs e)
        {
            Sync();
        }

        private void RefreshButtonClick(object sender, EventArgs e)
        {
            Log.Clear();
            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            syncBrowser.Document.InvokeScript("Start");
        }

        private void LoadScript(string fileName)
        {
            var fileContent = File.ReadAllText(Publisher.ScriptPath(fileName));
            if (!String.IsNullOrEmpty(fileContent))
            {
                Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
                var head = syncBrowser.Document.GetElementsByTagName("head")[0];
                var scriptEl = syncBrowser.Document.CreateElement("script");
                Debug.Assert(scriptEl != null, "scriptEl != null");
                var element = (IHTMLScriptElement)scriptEl.DomElement;
                element.text = fileContent;
                head.AppendChild(scriptEl);
            }
        }

        private void SyncBrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            LoadScript("Scripts/jquery-1.6.2.js");
            LoadScript("Scripts/lib.json.js");
            LoadScript("Scripts/mscorlib.js");
            LoadScript("Scripts/Nsb.js");
            LoadScript("Scripts/SyncJS.js");

            Debug.Assert(syncBrowser.Document != null, "syncBrowser.Document != null");
            syncBrowser.Document.InvokeScript("Start");
        }

    }
}
